#※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
# File Name: system.sh
# Author: GID5564
# Description: functions for system
# Created Time: 07/11/23-19:37:13
#※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
#! /usr/bin/env bash

# 避免重复导入
#[[ -n $__XLIB_IMPORTED__SYSTEM ]] && return 0
#__XLIB_IMPORTED__SYSTEM=1

function __system_init__() {
    if [[ -z $(command -v ip) ]];then
        #ip route
        apt install iproute2
    fi

    #设置全局变量
    export SYSTEM_CONFIG="${CONFIG_PATH}/.system"

    export KERNEL_NAME="" #linux
    export KERNEL_VERSION=""  #5.4.0-aidlite
    export KERNEL_MACHINE=""  #aarch64
    export DARWIN_NAME=""
    export OSX_VERSION=""
    export OSX_BUILD=""
    
    __cache_uname__
    
    if [[ ! -s ${SYSTEM_CONFIG} ]];then
        [[ ! -d ${CONFIG_PATH} ]] && mkdir ${CONFIG_PATH}
        __write_config_system__
    fi
    #读取配置
    __read_config_system__
    
    export CURRENT_OPERATING_SYSTEM=$(get_os)
    export CURRENT_SYSTEM_DISTRO=$(get_distro)
    export CURRENT_SHELL=$(get_current_shell "off")
    
    get_cache_dir
}


function __write_config_system__(){
    cat >>${SYSTEM_CONFIG} <<-'EOF'
[system]
## system.sh default config
##注: 等号两边各有一个空格，且无引号

# Show/Hide OS Architecture.
# Default: 'on'
# Values:  'on', 'off'
# Flag:    --os_arch
#
# Example:
# on:  'Arch Linux x86_64'
# off: 'Arch Linux'
os_arch = on

# Display CPU cores in output
# Default: 'logical'
# Values:  'logical', 'physical', 'off'
# Flag:    --cpu_cores
# Support: 'physical' doesn't work on BSD.
#
# Example:
# logical:  'Intel i7-6500U (4) @ 3.1GHz' (All virtual cores)
# physical: 'Intel i7-6500U (2) @ 3.1GHz' (All physical cores)
# off:      'Intel i7-6500U @ 3.1GHz'
cpu_cores = logical

# Hide/Show CPU speed.
# Default: 'on'
# Values:  'on', 'off'
# Flag:    --cpu_speed
#
# Example:
# on:  'Intel i7-6500U (4) @ 3.1GHz'
# off: 'Intel i7-6500U (4)'
cpu_speed = on

# Hide/Show CPU temperature.
# Note the temperature is added to the regular CPU function.
# Default: 'off'
# Values:  'C', 'F', 'off'
# Flag:    --cpu_temp
# Supports: Linux, BSD
# NOTE: For FreeBSD and NetBSD-based systems, you'll need to enable
#       coretemp kernel module. This only supports newer Intel processors.
#
# Example:
# C:   'Intel i7-6500U (4) @ 3.1GHz [27.2°C]'
# F:   'Intel i7-6500U (4) @ 3.1GHz [82.0°F]'
# off: 'Intel i7-6500U (4) @ 3.1GHz'
cpu_temp = off

# Shorten the output of the uptime function
# Default: 'on'
# Values:  'on', 'off', 'tiny'
# Flag:    --uptime_shorthand
#
# Example:
# on:   '2 days, 10 hours, 3 mins'
# off:  '2 days, 10 hours, 3 minutes'
# tiny: '2d 10h 3m'
uptime_shorthand = on

# Show memory pecentage in output.
# Default: 'off'
# Values:  'on', 'off'
# Flag:    --memory_percent
#
# Example:
# on:   '1801MiB / 7881MiB (22%)'
# off:  '1801MiB / 7881MiB'
memory_percent = off

# Change memory output unit.
#
# Default: 'mib'
# Values:  'kib', 'mib', 'gib'
# Flag:    --memory_unit
#
# Example:
# kib  '1020928KiB / 7117824KiB'
# mib  '1042MiB / 6951MiB'
# gib: ' 0.98GiB / 6.79GiB'
memory_unit = mib

# CPU speed shorthand
# Default: 'off'
# Values: 'on', 'off'.
# Flag:    --speed_shorthand
# NOTE: This flag is not supported in systems with CPU speed less than 1 GHz
#
# Example:
# on:    'i7-6500U (4) @ 3.1GHz'
# off:   'i7-6500U (4) @ 3.100GHz'
speed_shorthand = off

# CPU speed type
# Default: 'bios_limit'
# Values: 'scaling_cur_freq', 'scaling_min_freq', 'scaling_max_freq', 'bios_limit'.
# Flag:    --speed_type
# Supports: Linux with 'cpufreq'
# NOTE: Any file in '/sys/devices/system/cpu/cpu0/cpufreq' can be used as a value.
speed_type = scaling_cur_freq

# Shorten the output of the distro function
# Default:  'off'
# Values:   'on', 'off', 'tiny'
# Flag:     --distro_shorthand
# Supports: Everything except Windows and Haiku
distro_shorthand = off

# Shorten the output of the kernel function.
# Default:  'on'
# Values:   'on', 'off'
# Flag:     --kernel_shorthand
# Supports: Everything except *BSDs (except PacBSD and PC-BSD)
#
# Example:
# on:  '4.8.9-1-ARCH'
# off: 'Linux 4.8.9-1-ARCH'
kernel_shorthand = on

# Enable/Disable GPU Brand
#
# Default: 'on'
# Values:  'on', 'off'
# Flag:    --gpu_brand
#
# Example:
# on:  'AMD HD 7950'
# off: 'HD 7950'
gpu_brand = on

# Which GPU to display
#
# Default: 'all'
# Values:  'all', 'dedicated', 'integrated'
# Flag:    --gpu_type
# Supports: Linux
#
# Example:
# all:
#   GPU1: AMD HD 7950
#   GPU2: Intel Integrated Graphics
#
# dedicated:
#   GPU1: AMD HD 7950
#
# integrated:
#   GPU1: Intel Integrated Graphics
gpu_type = all


# Website to ping for the public IP
#
# Default: 'https://www.baidu.com'
# Values:  'url'
# Flag:    --ip_host
public_ip_host = https://www.baidu.com

# Public IP timeout.
#
# Default: '2'
# Values:  'int'
# Flag:    --ip_timeout
public_ip_timeout = 2

# Local IP interface
#
# Default: 'auto' (interface of default route)
# Values:  'auto', 'en0', 'en1'
# Flag:    --ip_interface
local_ip_interface = auto


# Image backend.
#
# Default:  'ascii'
# Values:   'ascii', 'caca', 'catimg', 'chafa', 'jp2a', 'iterm2', 'off',
#           'pot', 'termpix', 'pixterm', 'tycat', 'w3m', 'kitty', 'ueberzug',
#           'viu'
# Flag:     --backend
image_backend = ascii


EOF
}

function __read_config_system__(){
    import ini
    declare -g image_backend=$(read_ini $SYSTEM_CONFIG "system" "image_backend")

    declare -g public_ip_timeout=$(read_ini $SYSTEM_CONFIG "system" "public_ip_timeout")
    
    declare -g local_ip_interface=$(read_ini $SYSTEM_CONFIG "system" "local_ip_interface")

    declare -g cpu_cores=$(read_ini $SYSTEM_CONFIG "system" "cpu_cores")
    
    declare -g uptime_shorthand=$(read_ini $SYSTEM_CONFIG "system" "uptime_shorthand")
    
    declare -g memory_percent=$(read_ini $SYSTEM_CONFIG "system" "memory_percent")
    
    declare -g memory_unit=$(read_ini $SYSTEM_CONFIG "system" "memory_unit")

    declare -g cpu_speed=$(read_ini $SYSTEM_CONFIG "system" "cpu_speed")
    
    declare -g cpu_temp=$(read_ini $SYSTEM_CONFIG "system" "cpu_temp")
    
    declare -g speed_shorthand=$(read_ini $SYSTEM_CONFIG "system" "speed_shorthand")
    
    declare -g speed_type=$(read_ini $SYSTEM_CONFIG "system" "speed_type")
    
    declare -g os_arch=$(read_ini $SYSTEM_CONFIG "system" "os_arch")
    
    declare -g distro_shorthand=$(read_ini $SYSTEM_CONFIG "system" "distro_shorthand")
    
    declare -g kernel_shorthand=$(read_ini $SYSTEM_CONFIG "system" "kernel_shorthand")

    declare -g gpu_brand=$(read_ini $SYSTEM_CONFIG "system" "gpu_brand")
    
    declare -g gpu_type=$(read_ini $SYSTEM_CONFIG "system" "gpu_type")

}


function cache() {
    if [[ "$2" ]]; then
        mkdir -p "${cache_dir}"
        printf "%s" "${1/*-}=\"$2\"" > "${cache_dir}/${1/*-}"
    fi
}
function get_cache_dir(){
    case $CURRENT_OPERATING_SYSTEM in
        "Mac OS X"|"macOS") export cache_dir="/Library/Caches" ;;
        *)          export cache_dir="/tmp" ;;
    esac
}

########################################
# 描述: 检测linux版本,OS版本,包管理器类型
# 参数: 
# 返回: 
#       
# 实例: check_system
########################################
function check_system() {
    local support=0
    local sys="$(uname -o)"
    case "${sys}" in
	GNU/Linux | Linux | linux) 
	    local PREFIX='/usr/local'
		[[ -d ${PREFIX} ]] || PREFIX='/usr'
		if [[ -e /etc/os-release ]]; then
		    support=1
	    else
	        if [[ $(command -v dpkg) && $(command -v apt) ]]; then
		        support=1
	        fi
	    fi
		;;
	*)
	    support=0
	    ;;
	esac
	echo $support
	unset sys
	unset support
	unset PREFIX
	
}

########################################
# 描述: 操作系统位数(32/64/...)
# 参数: 
# 返回: 位数
# 实例: OperatingSystemBit
########################################
function get_os_bit(){
    local bit
    bit=$(getconf LONG_BIT)
    printf '%s' ${bit}
    unset bit
}
########################################
# 描述: 系统架构类型
# 参数: 
# 返回: 系统架构
# 实例: SystemArchitecture
########################################
function get_system_architecture() {
    local DPKG_ARCH
    local ARCH_TYPE
    local UNAME_ARCH
    if [[ $(command -v dpkg) && $(command -v apt-get) ]]; then
        DPKG_ARCH=$(dpkg --print-architecture)
        case ${DPKG_ARCH} in
        armel) ARCH_TYPE="armel" ;;
        armv7* | armv8l | armhf | arm) ARCH_TYPE="armhf" ;;
        aarch64 | arm64* | armv8* | arm*) ARCH_TYPE="arm64" ;;
        i*86 | x86) ARCH_TYPE="i386" ;;
        x86_64 | amd64) ARCH_TYPE="amd64" ;;
        *) ARCH_TYPE=${DPKG_ARCH} ;;
        esac
    else
        UNAME_ARCH=$(uname -m)
        case ${UNAME_ARCH} in
        armv7* | armv8l) ARCH_TYPE="armhf" ;;
        armv6* | armv5*) ARCH_TYPE="armel" ;;
        aarch64 | armv8* | arm64) ARCH_TYPE="arm64" ;;
        x86_64 | amd64) ARCH_TYPE="amd64" ;;
        i*86 | x86) ARCH_TYPE="i386" ;;
        s390*) ARCH_TYPE="s390x" ;;
        ppc*) ARCH_TYPE="ppc64el" ;;
        mips64) ARCH_TYPE="mips64el" ;;
        mips*) ARCH_TYPE="mipsel" ;;
        risc*) ARCH_TYPE="riscv64" ;;
        *) ARCH_TYPE=${UNAME_ARCH} ;;
        esac
    fi
    printf '%s' ${ARCH_TYPE}
    unset DPKG_ARCH
    unset ARCH_TYPE
    unset UNAME_ARCH
}

########################################
# 描述: 当前用户和组
# 参数: 
# 返回: 当前用户,组
# 实例: GetCurrentUserAndGroup
########################################
function get_current_user_and_group(){

    local USER_NAME=$(grep "${HOME}" /etc/passwd | awk -F ':' '{print $1}' | head -n 1)
    local USER_GROUP=$(grep "${HOME}" /etc/passwd | awk -F ':' '{print $4}' | cut -d ',' -f 1 | head -n 1)
    if [ -z "${USER_GROUP}" ]; then
        USER_GROUP=${USER_NAME}
    fi
    printf '%s\n' "${USER_NAME},${USER_GROUP}"
    unset USER_NAME
    unset USER_GROUP
}

########################################
# 描述: 获取内核名称、版本和机器类型。缓存uname命令的输出，避免多次调用
# 参数: 
# 返回: 
#      KERNEL_NAME: 内核名称
#      KERNEL_VERSION: 内核版本
#      KERNEL_MACHINE: 机器类型
#      如果是 macOS 系统，有以下返回: 
#      DARWIN_NAME
#      OSX_VERSION
#      OSX_BUILD
#      
# 实例: __cache_uname__
########################################
function __cache_uname__(){
    # 获取内核名称、版本和机器类型
    KERNEL_NAME="$(uname -s)"
    KERNEL_VERSION="$(uname -r)"
    KERNEL_MACHINE="$(uname -m)"

    # 如果是 macOS 系统
    if [[ "$KERNEL_NAME" == "Darwin" ]]; then
        # 设置环境变量 SYSTEM_VERSION_COMPAT 为 0，以解决 macOS 版本显示错误的问题
        export SYSTEM_VERSION_COMPAT=0

        # 使用 awk 命令解析 SystemVersion.plist 文件，获取系统信息
        IFS=$'\n' read -d "" -ra sw_vers <<< "$(awk -F'<|>' '/key|string/ {print $3}' \n                            "/System/Library/CoreServices/SystemVersion.plist")"
        # 遍历解析结果，将关键信息存储到相应的变量中
        for ((i=0;i<${#sw_vers[@]};i+=2)) {
            case ${sw_vers[i]} in
                ProductName)          DARWIN_NAME=${sw_vers[i+1]} ;;
                ProductVersion)       OSX_VERSION=${sw_vers[i+1]} ;;
                ProductBuildVersion)  OSX_BUILD=${sw_vers[i+1]}   ;;
            esac
        }
    fi
}

########################################
# 描述: 获取操作系统名称os
# 参数: KERNEL_NAME
# 返回: os
# 实例: get_os
########################################
function get_os(){
    local os=""
    # $KERNEL_NAME 变量在 __cache_uname__ 函数中设置，其值为 "uname -s" 命令的输出
    case $KERNEL_NAME in
        Darwin)   # 如果内核名称为 Darwin (macOS)，则 os 变量设置为 DARWIN_NAME
            os=$DARWIN_NAME ;;
        SunOS)    # 如果内核名称为 SunOS，则 os 变量设置为 Solaris
            os=Solaris ;;
        Haiku)    # 如果内核名称为 Haiku，则 os 变量设置为 Haiku
            os=Haiku ;;
        MINIX)    # 如果内核名称为 MINIX，则 os 变量设置为 MINIX
            os=MINIX ;;
        AIX)      # 如果内核名称为 AIX，则 os 变量设置为 AIX
            os=AIX ;;
        IRIX*)    # 如果内核名称以 IRIX 开头，则 os 变量设置为 IRIX
            os=IRIX ;;
        FreeMiNT) # 如果内核名称为 FreeMiNT，则 os 变量设置为 FreeMiNT
            os=FreeMiNT ;;

        Linux|GNU*)
            # 如果内核名称为 Linux 或 GNU，则 os 变量设置为 Linux
            os=Linux
        ;;

        *BSD|DragonFly|Bitrig)
            # 如果内核名称为 BSD、DragonFly 或 Bitrig，则 os 变量设置为 BSD
            os=BSD
        ;;

        CYGWIN*|MSYS*|MINGW*)
            # 如果内核名称为 CYGWIN、MSYS 或 MINGW，则 os 变量设置为 Windows
            os=Windows
        ;;

        *)
            # 如果内核名称不在上述列表中，打印错误信息并退出脚本
            printf '%s' "Unknown OS detected: '$KERNEL_NAME', aborting..." >&2
            printf '%s' "Open an issue on GitHub to add support for your OS." >&2
            exit 1
        ;;
    esac
    printf '%s' $os
    unset os
}
########################################
# 描述: 获取当前操作系统的发行版名称
# 参数: CURRENT_OPERATING_SYSTEM
# 返回: 发行版名称:distro
# 实例: get_distro
########################################
function get_distro() {
    local distro
    case $CURRENT_OPERATING_SYSTEM in
        Linux|BSD|MINIX)
            if [[ -f /bedrock/etc/bedrock-release && -z $BEDROCK_RESTRICT ]]; then
                case $distro_shorthand in
                    on|tiny) distro="Bedrock Linux" ;;
                    *) distro=$(< /bedrock/etc/bedrock-release)
                esac

            elif [[ -f /etc/redstar-release ]]; then
                case $distro_shorthand in
                    on|tiny) distro="Red Star OS" ;;
                    *) distro="Red Star OS $(awk -F'[^0-9*]' '$0=$2' /etc/redstar-release)"
                esac

            elif [[ -f /etc/armbian-release ]]; then
                . /etc/armbian-release
                distro="Armbian $DISTRIBUTION_CODENAME (${VERSION:-})"

            elif [[ -f /etc/siduction-version ]]; then
                case $distro_shorthand in
                    on|tiny) distro=Siduction ;;
                    *) distro="Siduction ($(lsb_release -sic))"
                esac

            elif [[ -f /etc/mcst_version ]]; then
                case $distro_shorthand in
                    on|tiny) distro="OS Elbrus" ;;
                    *) distro="OS Elbrus $(< /etc/mcst_version)"
                esac

            elif type -p pveversion >/dev/null; then
                case $distro_shorthand in
                    on|tiny) distro="Proxmox VE" ;;
                    *)
                        distro=$(pveversion)
                        distro=${distro#pve-manager/}
                        distro="Proxmox VE ${distro%/*}"
                esac

            elif type -p lsb_release >/dev/null; then
                case $distro_shorthand in
                    on)   lsb_flags=-si ;;
                    tiny) lsb_flags=-si ;;
                    *)    lsb_flags=-sd ;;
                esac
                distro=$(lsb_release "$lsb_flags")

            elif [[ -f /etc/os-release || \
                    -f /usr/lib/os-release || \
                    -f /etc/openwrt_release || \
                    -f /etc/lsb-release ]]; then

                # Source the os-release file
                local file
                for file in /etc/lsb-release /usr/lib/os-release \
                            /etc/os-release  /etc/openwrt_release; do
                    source "$file" && break
                done
                unset file

                # Format the distro name.
                case $distro_shorthand in
                    on)   distro="${NAME:-${DISTRIB_ID}} ${VERSION_ID:-${DISTRIB_RELEASE}}" ;;
                    tiny) distro="${NAME:-${DISTRIB_ID:-${TAILS_PRODUCT_NAME}}}" ;;
                    off)  distro="${PRETTY_NAME:-${DISTRIB_DESCRIPTION}} ${UBUNTU_CODENAME}" ;;
                esac

            elif [[ -f /etc/GoboLinuxVersion ]]; then
                case $distro_shorthand in
                    on|tiny) distro=GoboLinux ;;
                    *) distro="GoboLinux $(< /etc/GoboLinuxVersion)"
                esac

            elif [[ -f /etc/SDE-VERSION ]]; then
                distro="$(< /etc/SDE-VERSION)"
                case $distro_shorthand in
                    on|tiny) distro="${distro% *}" ;;
                esac

            elif type -p crux >/dev/null; then
                distro=$(crux)
                case $distro_shorthand in
                    on)   distro=${distro//version} ;;
                    tiny) distro=${distro//version*}
                esac

            elif type -p tazpkg >/dev/null; then
                distro="SliTaz $(< /etc/slitaz-release)"

            elif type -p kpt >/dev/null && \
                 type -p kpm >/dev/null; then
                distro=KSLinux

            elif [[ -d /system/app/ && -d /system/priv-app ]]; then
                distro="Android $(getprop ro.build.version.release)"

            # Chrome OS doesn't conform to the /etc/*-release standard.
            # While the file is a series of variables they can't be sourced
            # by the shell since the values aren't quoted.
            elif [[ -f /etc/lsb-release && $(< /etc/lsb-release) == *CHROMEOS* ]]; then
                distro='Chrome OS'

            elif type -p guix >/dev/null; then
                case $distro_shorthand in
                    on|tiny) distro="Guix System" ;;
                    *) distro="Guix System $(guix -V | awk 'NR==1{printf $4}')"
                esac

            # Display whether using '-current' or '-release' on OpenBSD.
            elif [[ $KERNEL_NAME = OpenBSD ]] ; then
                read -ra kernel_info <<< "$(sysctl -n kern.version)"
                distro=${kernel_info[*]:0:2}

            else
                local release_file
                for release_file in /etc/*-release; do
                    distro+=$(< "$release_file")
                done
                unset release_file

                if [[ -z $distro ]]; then
                    case $distro_shorthand in
                        on|tiny) distro=$KERNEL_NAME ;;
                        *) distro="$KERNEL_NAME $KERNEL_VERSION" ;;
                    esac

                    distro=${distro/DragonFly/DragonFlyBSD}

                    # Workarounds for some BSD based distros.
                    [[ -f /etc/pcbsd-lang ]]       && distro=PCBSD
                    [[ -f /etc/trueos-lang ]]      && distro=TrueOS
                    [[ -f /etc/pacbsd-release ]]   && distro=PacBSD
                    [[ -f /etc/hbsd-update.conf ]] && distro=HardenedBSD
                fi
            fi

            if [[ $(< /proc/version) == *Microsoft* || $KERNEL_VERSION == *Microsoft* ]]; then
               local windows_version=$(wmic.exe os get Version)
                windows_version=$(trim "${windows_version/Version}")

                case $distro_shorthand in
                    on)   distro+=" [Windows $windows_version]" ;;
                    tiny) distro="Windows ${windows_version::2}" ;;
                    *)    distro+=" on Windows $windows_version" ;;
                esac
            unset windows_version
            elif [[ $(< /proc/version) == *chrome-bot* || -f /dev/cros_ec ]]; then
                [[ $distro != *Chrome* ]] &&
                    case $distro_shorthand in
                        on)   distro+=" [Chrome OS]" ;;
                        tiny) distro="Chrome OS" ;;
                        *)    distro+=" on Chrome OS" ;;
                    esac
                    distro=${distro## on }
            fi

            #distro=$(qtrim "$distro")
            distro=${distro//\'/}
            distro=${distro//\"/}
            distro=${distro/NAME=}

            # Get Ubuntu flavor.
            if [[ $distro == "Ubuntu"* ]]; then
                case $XDG_CONFIG_DIRS in
                    *"studio"*)   distro=${distro/Ubuntu/Ubuntu Studio} ;;
                    *"plasma"*)   distro=${distro/Ubuntu/Kubuntu} ;;
                    *"mate"*)     distro=${distro/Ubuntu/Ubuntu MATE} ;;
                    *"xubuntu"*)  distro=${distro/Ubuntu/Xubuntu} ;;
                    *"Lubuntu"*)  distro=${distro/Ubuntu/Lubuntu} ;;
                    *"budgie"*)   distro=${distro/Ubuntu/Ubuntu Budgie} ;;
                    *"cinnamon"*) distro=${distro/Ubuntu/Ubuntu Cinnamon} ;;
                esac
            fi
        ;;

        "Mac OS X"|"macOS")
            case $OSX_VERSION in
                10.4*)  codename="Mac OS X Tiger" ;;
                10.5*)  codename="Mac OS X Leopard" ;;
                10.6*)  codename="Mac OS X Snow Leopard" ;;
                10.7*)  codename="Mac OS X Lion" ;;
                10.8*)  codename="OS X Mountain Lion" ;;
                10.9*)  codename="OS X Mavericks" ;;
                10.10*) codename="OS X Yosemite" ;;
                10.11*) codename="OS X El Capitan" ;;
                10.12*) codename="macOS Sierra" ;;
                10.13*) codename="macOS High Sierra" ;;
                10.14*) codename="macOS Mojave" ;;
                10.15*) codename="macOS Catalina" ;;
                10.16*) codename="macOS Big Sur" ;;
                11.*)  codename="macOS Big Sur" ;;
                12.*)  codename="macOS Monterey" ;;
                *)      codename=macOS ;;
            esac

            distro="$codename $OSX_VERSION $OSX_BUILD"

            case $distro_shorthand in
                on) distro=${distro/ ${OSX_BUILD}} ;;

                tiny)
                    case $OSX_VERSION in
                        10.[4-7]*)            distro=${distro/${codename}/Mac OS X} ;;
                        10.[8-9]*|10.1[0-1]*) distro=${distro/${codename}/OS X} ;;
                        10.1[2-6]*|11.0*)     distro=${distro/${codename}/macOS} ;;
                    esac
                    distro=${distro/ ${OSX_BUILD}}
                ;;
            esac
        ;;

        "iPhone OS")
            distro="iOS $OSX_VERSION"

            # "uname -m" doesn't print architecture on iOS.
            os_arch=off
        ;;

        Windows)
            distro=$(wmic os get Caption)
            distro=${distro/Caption}
            distro=${distro/Microsoft }
        ;;

        Solaris)
            case $distro_shorthand in
                on|tiny) distro=$(awk 'NR==1 {print $1,$3}' /etc/release) ;;
                *)       distro=$(awk 'NR==1 {print $1,$2,$3}' /etc/release) ;;
            esac
            distro=${distro/\(*}
        ;;

        Haiku)
            distro=Haiku
        ;;

        AIX)
            distro="AIX $(oslevel)"
        ;;

        IRIX)
            distro="IRIX ${KERNEL_VERSION}"
        ;;

        FreeMiNT)
            distro=FreeMiNT
        ;;
    esac

    distro=${distro//Enterprise Server}

    [[ $distro ]] || distro="$CURRENT_OPERATING_SYSTEM (Unknown)"

    # Get OS architecture.
    local machine_arch
    case $CURRENT_OPERATING_SYSTEM in
        Solaris|AIX|Haiku|IRIX|FreeMiNT)
            machine_arch=$(uname -p)
        ;;

        *)  machine_arch=$KERNEL_MACHINE ;;
    esac

    [[ $os_arch == on ]] && \
        distro+=" $machine_arch"


    printf '%s' $distro
    unset machine_arch
    unset distro
}

########################################
# 描述: 获取当前操作系统的内核信息
# 参数: 
# 返回: 内核信息:kernel
# 实例: get_kernel
########################################
function get_kernel() {
    local kernel
    # 如果是AIX或IRIX操作系统，直接返回，因为这些是集成系统，不需要获取内核信息
    [[ $CURRENT_OPERATING_SYSTEM =~ (AIX|IRIX) ]] && return

    # Haiku操作系统使用'uname -v'命令获取内核版本，而不是'uname -r'
    [[ $CURRENT_OPERATING_SYSTEM == Haiku ]] && {
        kernel=$(uname -v)
        return
    }

    # 在Windows系统中，'uname'可能返回GNUenv的信息，因此使用wmic命令获取操作系统内核信息
    [[ $CURRENT_OPERATING_SYSTEM == Windows ]] && {
        kernel=$(wmic os get Version)
        kernel=${kernel/Version}
        return
    }

    # 根据kernel_shorthand的值设置kernel变量
    case $kernel_shorthand in
        on)  kernel=$KERNEL_VERSION ;; # 如果kernel_shorthand为on，只显示内核版本号
        off) kernel="$KERNEL_NAME $KERNEL_VERSION" ;; # 如果kernel_shorthand为off，显示内核名称和版本号
    esac

    # 如果操作系统是BSD或MINIX，并且内核信息与发行版信息相同，则隐藏内核信息
    [[ $CURRENT_OPERATING_SYSTEM =~ (BSD|MINIX) && $CURRENT_SYSTEM_DISTRO == *"$KERNEL_NAME"* ]] &&
        case $distro_shorthand in
            on|tiny) kernel=$KERNEL_VERSION ;; # 如果distro_shorthand为on或tiny，只显示内核版本号
            *)       unset kernel ;; # 否则，不显示内核信息
        esac
    printf '%s' ${kernel}
    unset kernel
}

########################################
# 描述: 获取当前CPU信息
# 参数: 
# 返回: CPU信息:cpu
# 实例: get_cpu
########################################
function get_cpu() {
    local cpu
    local speed
    local cores
    local deg

    case $CURRENT_OPERATING_SYSTEM in
        "Linux" | "MINIX" | "Windows")
            # Get CPU name.
            local cpu_file="/proc/cpuinfo"
            case $KERNEL_MACHINE in
                "frv" | "hppa" | "m68k" | "openrisc" | "or"* | "powerpc" | "ppc"* | "sparc"*)
                    cpu="$(awk -F':' '/^cpu\t|^CPU/ {printf $2; exit}' "$cpu_file")"
                ;;

                "s390"*)
                    cpu="$(awk -F'=' '/machine/ {print $4; exit}' "$cpu_file")"
                ;;

                "ia64" | "m32r")
                    cpu="$(awk -F':' '/model/ {print $2; exit}' "$cpu_file")"
                    [[ -z "$cpu" ]] && cpu="$(awk -F':' '/family/ {printf $2; exit}' "$cpu_file")"
                ;;

                *)
                    cpu="$(awk -F '\\s*: | @' \
                            '/model name|Hardware|Processor|^cpu model|chip type|^cpu type/ {
                            cpu=$2; if ($1 == "Hardware") exit } END { print cpu }' "$cpu_file")"
                ;;
            esac

            
            # Get CPU temp.

            local temp_dir
            local temp_dirs

            # Select the right temperature file.
            # /sys/class/thermal/*
        
            if [[ -d "/sys/class/thermal" ]];then
                for temp_dir in /sys/class/thermal/thermal_*; do
                    [[ "$(cat "${temp_dir}/type")" =~ (xo-therm-adc|x86_pkg_temp|CPU-temp) ]] && {
                        temp_dir=("$temp_dir"/temp)
                        break
                    }
                done
            else
                for temp_dir in /sys/class/hwmon/*; do
                    [[ "$(< "${temp_dir}/name")" =~ (cpu_thermal|coretemp|fam15h_power|k10temp) ]] && {
                        temp_dirs=("$temp_dir"/temp*_input)
                        temp_dir=${temp_dirs[0]}
                        break
                    }
                done
            fi
            
            [[ -f "$temp_dir" ]] && deg="$(($(cat "$temp_dir") * 100 / 10000))"
            unset temp_dir temp_dirs

            # Get CPU speed.
            local speed_dir="/sys/devices/system/cpu/cpu0/cpufreq"

            
            if [[ -d "$speed_dir" ]]; then
                # Fallback to bios_limit if $speed_type fails.
                speed="$(< "${speed_dir}/${speed_type}")" ||\
                speed="$(< "${speed_dir}/bios_limit")" ||\
                speed="$(< "${speed_dir}/scaling_max_freq")" ||\
                speed="$(< "${speed_dir}/cpuinfo_max_freq")"
                speed="$((speed / 1000))"

            else
                case $KERNEL_MACHINE in
                    "sparc"*)
                        # SPARC systems use a different file to expose clock speed information.
                        local speed_file="/sys/devices/system/cpu/cpu0/clock_tick"
                        speed="$(($(< "$speed_file") / 1000000))"
                        unset speed_file
                    ;;

                    *)
                        speed="$(awk -F ': |\\.' '/cpu MHz|^clock/ {printf $2; exit}' "$cpu_file")"
                        speed="${speed/MHz}"
                    ;;
                esac
            fi
            unset speed_dir 
            
            # Get CPU cores.
            case $KERNEL_MACHINE in
                "sparc"*)
                    case $cpu_cores in
                        # SPARC systems doesn't expose detailed topology information in
                        # /proc/cpuinfo so I have to use lscpu here.
                        "logical" | "on")
                            cores="$(lscpu | awk -F ': *' '/^CPU\(s\)/ {print $2}')"
                        ;;
                        "physical")
                            cores="$(lscpu | awk -F ': *' '/^Core\(s\) per socket/ {print $2}')"
                            local sockets="$(lscpu | awk -F ': *' '/^Socket\(s\)/ {print $2}')"
                            cores="$((sockets * cores))"
                            unset sockets
                        ;;
                    esac
                ;;

                *)
                    case $cpu_cores in
                        "logical" | "on")
                            cores="$(grep -c "^processor" "$cpu_file")"
                        ;;
                        "physical")
                            cores="$(awk '/^core id/&&!a[$0]++{++i} END {print i}' "$cpu_file")"
                        ;;
                    esac
                ;;
            esac
            unset cpu_file
        ;;

        "Mac OS X"|"macOS")
            cpu="$(sysctl -n machdep.cpu.brand_string)"

            # Get CPU cores.
            case $cpu_cores in
                "logical" | "on") cores="$(sysctl -n hw.logicalcpu_max)" ;;
                "physical")       cores="$(sysctl -n hw.physicalcpu_max)" ;;
            esac
        ;;

        "iPhone OS")
            case $KERNEL_MACHINE in
                "iPhone1,"[1-2] | "iPod1,1"): "Samsung S5L8900 (1) @ 412MHz" ;;
                "iPhone2,1"):                 "Samsung S5PC100 (1) @ 600MHz" ;;
                "iPhone3,"[1-3] | "iPod4,1"): "Apple A4 (1) @ 800MHz" ;;
                "iPhone4,1" | "iPod5,1"):     "Apple A5 (2) @ 800MHz" ;;
                "iPhone5,"[1-4]): "Apple A6 (2) @ 1.3GHz" ;;
                "iPhone6,"[1-2]): "Apple A7 (2) @ 1.3GHz" ;;
                "iPhone7,"[1-2]): "Apple A8 (2) @ 1.4GHz" ;;
                "iPhone8,"[1-4] | "iPad6,1"[12]): "Apple A9 (2) @ 1.85GHz" ;;
                "iPhone9,"[1-4] | "iPad7,"[5-6] | "iPad7,1"[1-2]):
                    "Apple A10 Fusion (4) @ 2.34GHz"
                ;;
                "iPhone10,"[1-6]): "Apple A11 Bionic (6) @ 2.39GHz" ;;
                "iPhone11,"[2468] | "iPad11,"[1-4] | "iPad11,"[6-7]): "Apple A12 Bionic (6) @ 2.49GHz" ;;
                "iPhone12,"[1358]): "Apple A13 Bionic (6) @ 2.65GHz" ;;
                "iPhone13,"[1-4] | "iPad13,"[1-2]): "Apple A14 Bionic (6) @ 3.00Ghz" ;;

                "iPod2,1"): "Samsung S5L8720 (1) @ 533MHz" ;;
                "iPod3,1"): "Samsung S5L8922 (1) @ 600MHz" ;;
                "iPod7,1"): "Apple A8 (2) @ 1.1GHz" ;;
                "iPad1,1"): "Apple A4 (1) @ 1GHz" ;;
                "iPad2,"[1-7]): "Apple A5 (2) @ 1GHz" ;;
                "iPad3,"[1-3]): "Apple A5X (2) @ 1GHz" ;;
                "iPad3,"[4-6]): "Apple A6X (2) @ 1.4GHz" ;;
                "iPad4,"[1-3]): "Apple A7 (2) @ 1.4GHz" ;;
                "iPad4,"[4-9]): "Apple A7 (2) @ 1.4GHz" ;;
                "iPad5,"[1-2]): "Apple A8 (2) @ 1.5GHz" ;;
                "iPad5,"[3-4]): "Apple A8X (3) @ 1.5GHz" ;;
                "iPad6,"[3-4]): "Apple A9X (2) @ 2.16GHz" ;;
                "iPad6,"[7-8]): "Apple A9X (2) @ 2.26GHz" ;;
                "iPad7,"[1-4]): "Apple A10X Fusion (6) @ 2.39GHz" ;;
                "iPad8,"[1-8]): "Apple A12X Bionic (8) @ 2.49GHz" ;;
                "iPad8,9" | "iPad8,1"[0-2]): "Apple A12Z Bionic (8) @ 2.49GHz" ;;
            esac
            cpu="$_"
        ;;

        "BSD")
            # Get CPU name.
            cpu="$(sysctl -n hw.model)"
            cpu="${cpu/[0-9]\.*}"
            cpu="${cpu/ @*}"

            # Get CPU speed.
            speed="$(sysctl -n hw.cpuspeed)"
            [[ -z "$speed" ]] && speed="$(sysctl -n  hw.clockrate)"

            # Get CPU cores.
            case $KERNEL_NAME in
                "OpenBSD"*)
                    [[ "$(sysctl -n hw.smt)" == "1" ]] && smt="on" || smt="off"
                    local ncpufound="$(sysctl -n hw.ncpufound)"
                    local ncpuonline="$(sysctl -n hw.ncpuonline)"
                    cores="${ncpuonline}/${ncpufound},\\xc2\\xa0SMT\\xc2\\xa0${smt}"
                    unset ncpufound ncpuonline
                ;;
                *)
                    cores="$(sysctl -n hw.ncpu)"
                ;;
            esac

            # Get CPU temp.
            case $KERNEL_NAME in
                "FreeBSD"* | "DragonFly"* | "NetBSD"*)
                    deg="$(sysctl -n dev.cpu.0.temperature)"
                    deg="${deg/C}"
                ;;
                "OpenBSD"* | "Bitrig"*)
                    deg="$(sysctl hw.sensors | \
                        awk -F'=|degC' '/(ksmn|adt|lm|cpu)0.temp0/ {printf("%2.1f", $2); exit}')"
                ;;
            esac
        ;;

        "Solaris")
            # Get CPU name.
            cpu="$(psrinfo -pv)"
            cpu="${cpu//*$'\n'}"
            cpu="${cpu/[0-9]\.*}"
            cpu="${cpu/ @*}"
            cpu="${cpu/\(portid*}"

            # Get CPU speed.
            speed="$(psrinfo -v | awk '/operates at/ {print $6; exit}')"

            # Get CPU cores.
            case $cpu_cores in
                "logical" | "on") cores="$(kstat -m cpu_info | grep -c -F "chip_id")" ;;
                "physical") cores="$(psrinfo -p)" ;;
            esac
        ;;

        "Haiku")
            # Get CPU name.
            cpu="$(sysinfo -cpu | awk -F '\\"' '/CPU #0/ {print $2}')"
            cpu="${cpu/@*}"

            # Get CPU speed.
            speed="$(sysinfo -cpu | awk '/running at/ {print $NF; exit}')"
            speed="${speed/MHz}"

            # Get CPU cores.
            cores="$(sysinfo -cpu | grep -c -F 'CPU #')"
        ;;

        "AIX")
            # Get CPU name.
            cpu="$(lsattr -El proc0 -a type | awk '{printf $2}')"

            # Get CPU speed.
            speed="$(prtconf -s | awk -F':' '{printf $2}')"
            speed="${speed/MHz}"

            # Get CPU cores.
            case $cpu_cores in
                "logical" | "on")
                    cores="$(lparstat -i | awk -F':' '/Online Virtual CPUs/ {printf $2}')"
                ;;

                "physical")
                    cores="$(lparstat -i | awk -F':' '/Active Physical CPUs/ {printf $2}')"
                ;;
            esac
        ;;

        "IRIX")
            # Get CPU name.
            cpu="$(hinv -c processor | awk -F':' '/CPU:/ {printf $2}')"

            # Get CPU speed.
            speed="$(hinv -c processor | awk '/MHZ/ {printf $2}')"

            # Get CPU cores.
            cores="$(sysconf NPROC_ONLN)"
        ;;

        "FreeMiNT")
            cpu="$(awk -F':' '/CPU:/ {printf $2}' /kern/cpuinfo)"
            speed="$(awk -F '[:.M]' '/Clocking:/ {printf $2}' /kern/cpuinfo)"
        ;;
    esac

    # Remove un-needed patterns from cpu output.
    cpu="${cpu//(TM)}"
    cpu="${cpu//(tm)}"
    cpu="${cpu//(R)}"
    cpu="${cpu//(r)}"
    cpu="${cpu//CPU}"
    cpu="${cpu//Processor}"
    cpu="${cpu//Dual-Core}"
    cpu="${cpu//Quad-Core}"
    cpu="${cpu//Six-Core}"
    cpu="${cpu//Eight-Core}"
    cpu="${cpu//[1-9][0-9]-Core}"
    cpu="${cpu//[0-9]-Core}"
    cpu="${cpu//, * Compute Cores}"
    cpu="${cpu//Core / }"
    cpu="${cpu//(\"AuthenticAMD\"*)}"
    cpu="${cpu//with Radeon * Graphics}"
    cpu="${cpu//, altivec supported}"
    cpu="${cpu//FPU*}"
    cpu="${cpu//Chip Revision*}"
    cpu="${cpu//Technologies, Inc}"
    cpu="${cpu//Core2/Core 2}"

    # Trim spaces from core and speed output
    cores="${cores//[[:space:]]}"
    speed="${speed//[[:space:]]}"

    # Remove CPU brand from the output.
    if [[ "$cpu_brand" == "off" ]]; then
        cpu="${cpu/AMD }"
        cpu="${cpu/Intel }"
        cpu="${cpu/Core? Duo }"
        cpu="${cpu/Qualcomm }"
    fi

    # Add CPU cores to the output.
    [[ "$cpu_cores" != "off" && "$cores" ]] && \
        case $CURRENT_OPERATING_SYSTEM in
            "Mac OS X"|"macOS") cpu="${cpu/@/(${cores}) @}" ;;
            *)                  cpu="$cpu ($cores)" ;;
        esac

    # Add CPU speed to the output.
    if [[ "$cpu_speed" != "off" && "$speed" ]]; then
        if (( speed < 1000 )); then
            cpu="$cpu @ ${speed}MHz"
        else
            [[ "$speed_shorthand" == "on" ]] && speed="$((speed / 100))"
            speed="${speed:0:1}.${speed:1}"
            cpu="$cpu @ ${speed}GHz"
        fi
    fi

    # Add CPU temp to the output.
    if [[ "$cpu_temp" != "off" && "$deg" ]]; then
        deg="${deg//.}"

        # Convert to Fahrenheit if enabled
        [[ "$cpu_temp" == "F" ]] && deg="$((deg * 90 / 50 + 320))"

        # Format the output
        deg="[${deg/${deg: -1}}.${deg: -1}°${cpu_temp:-C}]"
        cpu="$cpu $deg"
    fi
    printf '%s' ${cpu}
    unset cores cpu deg speed
}

########################################
# 描述: 获取当前GPU信息
# 参数: 
# 返回: GPU信息:gpu
# 实例: get_gpu
########################################
function get_gpu() {
    local gpu
    case $CURRENT_OPERATING_SYSTEM in
        "Linux")
            # Read GPUs into array.
            local gpu_cmd="$(lspci -mm |
                       awk -F '\"|\" \"|\\(' \
                              '/"Display|"3D|"VGA/ {
                                  a[$0] = $1 " " $3 " " ($(NF-1) ~ /^$|^Device [[:xdigit:]]+$/ ? $4 : $(NF-1))
                              }
                              END { for (i in a) {
                                  if (!seen[a[i]]++) {
                                      sub("^[^ ]+ ", "", a[i]);
                                      print a[i]
                                  }
                              }}')"
            IFS=$'\n' read -d "" -ra gpus <<< "$gpu_cmd"
            unset gpu_cmd

            # Remove duplicate Intel Graphics outputs.
            # This fixes cases where the outputs are both
            # Intel but not entirely identical.
            #
            # Checking the first two array elements should
            # be safe since there won't be 2 intel outputs if
            # there's a dedicated GPU in play.
            [[ "${gpus[0]}" == *Intel* && "${gpus[1]}" == *Intel* ]] && unset -v "gpus[0]"

            for gpu in "${gpus[@]}"; do
                # GPU shorthand tests.
                [[ "$gpu_type" == "dedicated" && "$gpu" == *Intel* ]] || \
                [[ "$gpu_type" == "integrated" && ! "$gpu" == *Intel* ]] && \
                    { unset -v gpu; continue; }

                case $gpu in
                    *"Advanced"*)
                        local brand="${gpu/*AMD*ATI*/AMD ATI}"
                        brand="${brand:-${gpu/*AMD*/AMD}}"
                        brand="${brand:-${gpu/*ATI*/ATi}}"

                        gpu="${gpu/\[AMD\/ATI\] }"
                        gpu="${gpu/\[AMD\] }"
                        gpu="${gpu/OEM }"
                        gpu="${gpu/Advanced Micro Devices, Inc.}"
                        gpu="${gpu/*\[}"
                        gpu="${gpu/\]*}"
                        gpu="$brand $gpu"
                        unset brand
                    ;;

                    *"NVIDIA"*)
                        gpu="${gpu/*\[}"
                        gpu="${gpu/\]*}"
                        gpu="NVIDIA $gpu"
                    ;;

                    *"Intel"*)
                        gpu="${gpu/*Intel/Intel}"
                        gpu="${gpu/\(R\)}"
                        gpu="${gpu/Corporation}"
                        gpu="${gpu/ \(*}"
                        gpu="${gpu/Integrated Graphics Controller}"
                        gpu="${gpu/*Xeon*/Intel HD Graphics}"

                        [[ -z "$(trim "$gpu")" ]] && gpu="Intel Integrated Graphics"
                    ;;

                    *"MCST"*)
                        gpu="${gpu/*MCST*MGA2*/MCST MGA2}"
                    ;;

                    *"VirtualBox"*)
                        gpu="VirtualBox Graphics Adapter"
                    ;;

                    *) continue ;;
                esac

                if [[ "$gpu_brand" == "off" ]]; then
                    gpu="${gpu/AMD }"
                    gpu="${gpu/NVIDIA }"
                    gpu="${gpu/Intel }"
                fi

            done

            return
        ;;

        "Mac OS X"|"macOS")
            if [[ -f "${cache_dir}/gpu" ]]; then
                source "${cache_dir}/gpu"

            else
                gpu="$(system_profiler SPDisplaysDataType |\
                       awk -F': ' '/^\ *Chipset Model:/ {printf $2 ", "}')"
                gpu="${gpu//\/ \$}"
                gpu="${gpu%,*}"

                cache "gpu" "$gpu"
            fi
        ;;

        "iPhone OS")
            case $KERNEL_MACHINE in
                "iPhone1,"[1-2]):                             "PowerVR MBX Lite 3D" ;;
                "iPhone2,1" | "iPhone3,"[1-3] | "iPod3,1" | "iPod4,1" | "iPad1,1"):
                    "PowerVR SGX535"
                ;;
                "iPhone4,1" | "iPad2,"[1-7] | "iPod5,1"):     "PowerVR SGX543MP2" ;;
                "iPhone5,"[1-4]):                             "PowerVR SGX543MP3" ;;
                "iPhone6,"[1-2] | "iPad4,"[1-9]):             "PowerVR G6430" ;;
                "iPhone7,"[1-2] | "iPod7,1" | "iPad5,"[1-2]): "PowerVR GX6450" ;;
                "iPhone8,"[1-4] | "iPad6,1"[12]):             "PowerVR GT7600" ;;
                "iPhone9,"[1-4] | "iPad7,"[5-6]):             "PowerVR GT7600 Plus" ;;
                "iPhone10,"[1-6]):                            "Apple Designed GPU (A11)" ;;
                "iPhone11,"[2468] | "iPad11,"[67]):           "Apple Designed GPU (A12)" ;;
                "iPhone12,"[1358]):                           "Apple Designed GPU (A13)" ;;
                "iPhone13,"[1234] | "iPad13,"[12]):           "Apple Designed GPU (A14)" ;;

                "iPad3,"[1-3]):     "PowerVR SGX534MP4" ;;
                "iPad3,"[4-6]):     "PowerVR SGX554MP4" ;;
                "iPad5,"[3-4]):     "PowerVR GXA6850" ;;
                "iPad6,"[3-8]):     "PowerVR 7XT" ;;

                "iPod1,1" | "iPod2,1")
                    : "PowerVR MBX Lite"
                ;;
            esac
            gpu="$_"
        ;;

        "Windows")
            wmic path Win32_VideoController get caption | while read -r line; do
                line=$(trim "$line")

                case $line in
                    *Caption*|'')
                        continue
                    ;;

                    *)
                       # prin "${subtitle:+${subtitle}${gpu_name}}" "$line"
                        gpu=$line
                    ;;
                esac
            done
        ;;

        "Haiku")
            gpu="$(listdev | grep -A2 -F 'device Display controller' |\
                   awk -F':' '/device beef/ {print $2}')"
        ;;

        *)
            case $KERNEL_NAME in
                "FreeBSD"* | "DragonFly"*)
                    gpu="$(pciconf -lv | grep -B 4 -F "VGA" | grep -F "device")"
                    gpu="${gpu/*device*= }"
                    gpu="$(qtrim"$gpu")"
                ;;

                *)
                    gpu="$(glxinfo -B | grep -F 'OpenGL renderer string')"
                    gpu="${gpu/OpenGL renderer string: }"
                ;;
            esac
        ;;
    esac

    if [[ "$gpu_brand" == "off" ]]; then
        gpu="${gpu/AMD}"
        gpu="${gpu/NVIDIA}"
        gpu="${gpu/Intel}"
    fi
    
    printf '%s' ${gpu}
    unset gpu
}

########################################
# 描述: 获取当前内存信息
# 参数: 
# 返回: 内存信息:memory
# 实例: get_memory
########################################
function get_memory() {
    local mem_used
    local mem_free
    local mem_label
    local mem_total
    local mem_perc
    local mem_cmd
    local mem_avail

    case $CURRENT_OPERATING_SYSTEM in
        "Linux" | "Windows")
            # MemUsed = Memtotal + Shmem - MemFree - Buffers - Cached - SReclaimable
            # Source: https://github.com/KittyKatt/screenFetch/issues/386#issuecomment-249312716
            while IFS=":" read -r a b; do
                case $a in
                    "MemTotal") ((mem_used+=${b/kB})); mem_total="${b/kB}" ;;
                    "Shmem") ((mem_used+=${b/kB}))  ;;
                    "MemFree" | "Buffers" | "Cached" | "SReclaimable")
                        mem_used="$((mem_used-=${b/kB}))"
                    ;;

                    # Available since Linux 3.14rc (34e431b0ae398fc54ea69ff85ec700722c9da773).
                    # If detected this will be used over the above calculation for mem_used.
                    "MemAvailable")
                        mem_avail=${b/kB}
                    ;;
                esac
            done < /proc/meminfo

            if [[ $mem_avail ]]; then
                mem_used=$(((mem_total - mem_avail) / 1024))
            else
                mem_used="$((mem_used / 1024))"
            fi

            mem_total="$((mem_total / 1024))"
        ;;

        "Mac OS X" | "macOS" | "iPhone OS")
            local hw_pagesize="$(sysctl -n hw.pagesize)"
            mem_total="$(($(sysctl -n hw.memsize) / 1024 / 1024))"
            local pages_app="$(($(sysctl -n vm.page_pageable_internal_count) - $(sysctl -n vm.page_purgeable_count)))"
            local pages_wired="$(vm_stat | awk '/ wired/ { print $4 }')"
            local pages_compressed="$(vm_stat | awk '/ occupied/ { printf $5 }')"
            local pages_compressed="${pages_compressed:-0}"
            mem_used="$(((${pages_app} + ${pages_wired//.} + ${pages_compressed//.}) * hw_pagesize / 1024 / 1024))"
            unset hw_pagesize pages_app pages_wired pages_compressed
        ;;

        "BSD" | "MINIX")
            # Mem total.
            case $KERNEL_NAME in
                "NetBSD"*) mem_total="$(($(sysctl -n hw.physmem64) / 1024 / 1024))" ;;
                *) mem_total="$(($(sysctl -n hw.physmem) / 1024 / 1024))" ;;
            esac

            # Mem free.
            case $KERNEL_NAME in
                "NetBSD"*)
                    mem_free="$(($(awk -F ':|kB' '/MemFree:/ {printf $2}' /proc/meminfo) / 1024))"
                ;;

                "FreeBSD"* | "DragonFly"*)
                    local hw_pagesize="$(sysctl -n hw.pagesize)"
                    local mem_inactive="$(($(sysctl -n vm.stats.vm.v_inactive_count) * hw_pagesize))"
                    local mem_unused="$(($(sysctl -n vm.stats.vm.v_free_count) * hw_pagesize))"
                    local mem_cache="$(($(sysctl -n vm.stats.vm.v_cache_count) * hw_pagesize))"
                    mem_free="$(((mem_inactive + mem_unused + mem_cache) / 1024 / 1024))"
                    unset hw_pagesize mem_inactive mem_unused mem_cache
                ;;

                "MINIX")
                    mem_free="$(top -d 1 | awk -F ',' '/^Memory:/ {print $2}')"
                    mem_free="${mem_free/M Free}"
                ;;

                "OpenBSD"*) ;;
                *) mem_free="$(($(vmstat | awk 'END {printf $5}') / 1024))" ;;
            esac

            # Mem used.
            case $KERNEL_NAME in
                "OpenBSD"*)
                    mem_used="$(vmstat | awk 'END {printf $3}')"
                    mem_used="${mem_used/M}"
                ;;

                *) mem_used="$((mem_total - mem_free))" ;;
            esac
        ;;

        "Solaris" | "AIX")
            local hw_pagesize="$(pagesize)"
            local pages_total
            local pages_free
            case $CURRENT_OPERATING_SYSTEM in
                "Solaris")
                    pages_total="$(kstat -p unix:0:system_pages:pagestotal | awk '{print $2}')"
                    pages_free="$(kstat -p unix:0:system_pages:pagesfree | awk '{print $2}')"
                ;;

                "AIX")
                    IFS=$'\n'"| " read -d "" -ra mem_stat <<< "$(svmon -G -O unit=page)"
                    pages_total="${mem_stat[11]}"
                    pages_free="${mem_stat[16]}"
                ;;
            esac
            mem_total="$((pages_total * hw_pagesize / 1024 / 1024))"
            mem_free="$((pages_free * hw_pagesize / 1024 / 1024))"
            mem_used="$((mem_total - mem_free))"
            unset hw_pagesize pages_free pages_total
        ;;

        "Haiku")
            mem_total="$(($(sysinfo -mem | awk -F '\\/ |)' '{print $2; exit}') / 1024 / 1024))"
            mem_used="$(sysinfo -mem | awk -F '\\/|)' '{print $2; exit}')"
            mem_used="$((${mem_used/max} / 1024 / 1024))"
        ;;

        "IRIX")
            IFS=$'\n' read -d "" -ra mem_cmd <<< "$(pmem)"
            IFS=" " read -ra mem_stat <<< "${mem_cmd[0]}"

            mem_total="$((mem_stat[3] / 1024))"
            mem_free="$((mem_stat[5] / 1024))"
            mem_used="$((mem_total - mem_free))"
        ;;

        "FreeMiNT")
            local mem="$(awk -F ':|kB' '/MemTotal:|MemFree:/ {printf $2, " "}' /kern/meminfo)"
            mem_free="${mem/*  }"
            mem_total="${mem/$mem_free}"
            mem_used="$((mem_total - mem_free))"
            mem_total="$((mem_total / 1024))"
            mem_used="$((mem_used / 1024))"
            unset mem
        ;;

    esac

    [[ "$memory_percent" == "on" ]] && ((mem_perc=mem_used * 100 / mem_total))

    case $memory_unit in
        gib)
            mem_used=$(awk '{printf "%.2f", $1 / $2}' <<< "$mem_used 1024")
            mem_total=$(awk '{printf "%.2f", $1 / $2}' <<< "$mem_total 1024")
            mem_label=GiB
        ;;

        kib)
            mem_used=$((mem_used * 1024))
            mem_total=$((mem_total * 1024))
            mem_label=KiB
        ;;
    esac

    local memory="${mem_used}${mem_label:-MiB} / ${mem_total}${mem_label:-MiB} ${mem_perc:+(${mem_perc}%)}"

    printf '%s' ${memory}
    unset mem_used mem_free mem_label mem_total mem_perc mem_cmd memory mem_avail
}

########################################
# 描述: 获取系统运行时间(秒)
# 参数: 
# 返回: 运行时间:uptime
# 实例: get_uptime
########################################
function get_uptime() {
    # Get uptime in seconds.
    local uptime
    local s
    case $CURRENT_OPERATING_SYSTEM in
        Linux|Windows|MINIX)
            if [[ -r /proc/uptime ]]; then
                s=$(< /proc/uptime)
                s=${s/.*}
            else
                local boot=$(date -d"$(uptime -s)" +%s)
                local now=$(date +%s)
                s=$((now - boot))
                unset now boot
            fi
        ;;

        "Mac OS X"|"macOS"|"iPhone OS"|BSD|FreeMiNT)
            local boot=$(sysctl -n kern.boottime)
            boot=${boot/\{ sec = }
            boot=${boot/,*}

            # Get current date in seconds.
            local now=$(date +%s)
            s=$((now - boot))
            unset now boot
        ;;

        Solaris)
            s=$(kstat -p unix:0:system_misc:snaptime | awk '{print $2}')
            s=${s/.*}
        ;;

        AIX|IRIX)
            local t=$(LC_ALL=POSIX ps -o etime= -p 1)

            [[ $t == *-*   ]] && { local d=${t%%-*}; t=${t#*-}; }
            [[ $t == *:*:* ]] && { local h=${t%%:*}; t=${t#*:}; }

            h=${h#0}
            t=${t#0}

            s=$((${d:-0}*86400 + ${h:-0}*3600 + ${t%%:*}*60 + ${t#*:}))
            unset t d h
        ;;

        Haiku)
            s=$(($(system_time) / 1000000))
            # uptime -u
        ;;
    esac

    local d="$((s / 60 / 60 / 24)) days"
    local h="$((s / 60 / 60 % 24)) hours"
    local m="$((s / 60 % 60)) minutes"

    # Remove plural if < 2.
    ((${d/ *} == 1)) && d=${d/s}
    ((${h/ *} == 1)) && h=${h/s}
    ((${m/ *} == 1)) && m=${m/s}

    # Hide empty fields.
    ((${d/ *} == 0)) && unset d
    ((${h/ *} == 0)) && unset h
    ((${m/ *} == 0)) && unset m

    uptime=${d:+$d, }${h:+$h, }$m
    uptime=${uptime%', '}
    uptime=${uptime:-$s seconds}
    unset d h m
    # Make the output of uptime smaller.
    case $uptime_shorthand in
        on)
            uptime=${uptime/ minutes/ mins}
            uptime=${uptime/ minute/ min}
            uptime=${uptime/ seconds/ secs}
        ;;

        tiny)
            uptime=${uptime/ days/d}
            uptime=${uptime/ day/d}
            uptime=${uptime/ hours/h}
            uptime=${uptime/ hour/h}
            uptime=${uptime/ minutes/m}
            uptime=${uptime/ minute/m}
            uptime=${uptime/ seconds/s}
            uptime=${uptime//,}
        ;;
    esac
    printf '%s' ${uptime}
    unset uptime
}
########################################
# 描述: #进程占用的CPU百分比总和
# 参数: 
# 返回: 百分比:cpu_usage
# 实例: get_cpu_usage
########################################
function get_cpu_usage() {
    local cpu_usage
    local cores
    
    case "$CURRENT_OPERATING_SYSTEM" in
    "Windows")
        cpu_usage="$(wmic cpu get loadpercentage)"
        cpu_usage="${cpu_usage/LoadPercentage}"
        cpu_usage="${cpu_usage//[[:space:]]}"
        ;;

    *)
        # Get CPU cores if unset.
        if [[ "$cpu_cores" != "logical" ]]; then
            case "$CURRENT_OPERATING_SYSTEM" in
            "Linux" | "MINIX") 
                cores="$(grep -c "^processor" /proc/cpuinfo)" 
                ;;
            "Mac OS X")       
                cores="$(sysctl -n hw.logicalcpu_max)" 
                ;;
            "BSD")             
                cores="$(sysctl -n hw.ncpu)" 
                ;;
            "Solaris")         
                cores="$(kstat -m cpu_info | grep -c -F "chip_id")" 
                ;;
            "Haiku")           
                cores="$(sysinfo -cpu | grep -c -F 'CPU #')"
                ;;
            "iPhone OS")       
                cores="${cpu/*\(}"; cores="${cores/\)*}"
                ;;
            "IRIX")            
                cores="$(sysconf NPROC_ONLN)" 
                ;;
            "FreeMiNT")        
                cores="$(sysctl -n hw.ncpu)" 
                ;;
            "AIX")
                cores="$(lparstat -i | awk -F':' '/Online Virtual CPUs/ {printf $2}')"
                ;;
            esac
        fi
        cpu_usage="$(ps aux | awk 'BEGIN {sum=0} {sum+=$3}; END {print sum}')"
        cpu_usage="$((${cpu_usage/\.*} / ${cores:-1}))"
        ;;
    esac
    printf '%s' "${cpu_usage}%"
    unset cores
    unset cpu_usage
}


########################################
# 描述: 根据id获取父进程id
# 参数: $1,pid
# 返回: ppid
# 实例: get_parent_process_id <pid>
########################################
function get_parent_process_id() {
    local ppid
    
    # Get parent process ID of PID.
    case "$CURRENT_OPERATING_SYSTEM" in
    "Windows")
        ppid="$(ps -p "${1:-$PPID}" | awk '{printf $2}')"
        ppid="${ppid/PPID}"
        ;;

    "Linux")
        ppid="$(grep -i -F "PPid:" "/proc/${1:-$PPID}/status")"
        ppid="$(trim "${ppid/PPid:}")"
        ;;

    *)
        ppid="$(ps -p "${1:-$PPID}" -o ppid=)"
        ;;
    esac

    printf "%s" "$ppid"
    unset ppid
}


########################################
# 描述: 根据id获取进程名称
# 参数: $1,进程id
# 返回: 进程名
# 实例: get_process_name <pid>
########################################
function get_process_name() {
    # Get PID name.
    local name
    case "$CURRENT_OPERATING_SYSTEM" in
    "Windows")
        name="$(ps -p "${1:-$PPID}" | awk '{printf $8}')"
        name="${name/COMMAND}"
        name="${name/*\/}"
        ;;

    "Linux")
        name="$(< "/proc/${1:-$PPID}/comm")"
        ;;

    *)
        name="$(ps -p "${1:-$PPID}" -o comm=)"
        ;;
    esac

    printf "%s" "$name"
    unset name
}
########################################
# 描述: 获取终端名称
# 参数: 
# 返回: 终端名
# 实例: get_terminal
########################################
# 根据TERM_PROGRAM设置初始term值
function initialize_term() {
    local term=""
    case "$TERM_PROGRAM" in
        "iTerm.app")
            term="iTerm2"
            ;;
        "Terminal.app")
            term="Apple Terminal"
            ;;
        "Hyper")
            term="HyperTerm"
            ;;
        *)
            term="${TERM_PROGRAM%.app}"
            ;;
    esac
    echo "$term"
}

# 检查SSH连接并设置term值
function check_ssh_connection() {
    local term="$1"
    if [[ -n "$SSH_CONNECTION" ]]; then
        if [[ -n "$SSH_TTY" ]]; then
            term="$SSH_TTY"
        fi
    fi
    echo "$term"
}

# 获取终端类型的主函数
function get_terminal(){
    local term="$(initialize_term)"
    term="$(check_ssh_connection "$term")"
    
    if [[ -z "$term" ]]; then
        local parent="$$"  # 初始化为当前进程的PID
        local name=""
        
        while [[ -n "$parent" ]]; do
            parent=$(get_parent_process_id "$parent") || break
            name=$(get_process_name "$parent") || break
            sanitized_name="${name// /}"
            sanitized_name="${sanitized_name//\"/}"
            sanitized_name="${sanitized_name//\'/}"
            sanitized_name="${sanitized_name//(/}"
            sanitized_name="${sanitized_name//)/}"
            
            case "$sanitized_name" in
                "${SHELL##*/}"|*"sh"|"screen"|"su"*)
                    ;; # 忽略这些进程
                "login"*|*"Login"*|"init"|"(init)")
                    local tty_output=$(tty)
                    if [[ $? -eq 0 ]]; then
                        term="$(basename "$tty_output")"
                    else
                        term="unknown"
                    fi
                    unset $tty_output
                    break  # 确定终端类型后退出循环
                    ;;
                "gnome-terminal-"*)
                    term="gnome-terminal"
                    break
                    ;;
                "urxvtd")
                    term="urxvt"
                    break
                    ;;
                *"nvim"*)
                    term="Neovim Terminal"
                    break
                    ;;
                *"NeoVimServer"*)
                    term="VimR Terminal"
                    break
                    ;;
                "ruby"|"1"|"tmux"*|"systemd"|"sshd"*|"python"*|"USER"*"PID"*|"kdeinit"*|"launchd"*)
                    break  # 遇到这些进程时停止查找
                    ;;
                *)
                    term="${sanitized_name}"
                    break
                    ;;
            esac
        done
    fi
    
    # 如果term仍为空，设置为默认值
    if [[ -z "$term" ]]; then
        term="unknown"
    fi
    
    # 输出最终的term值
    printf '%s\n' "$term"
    unset term
}


########################################
# 描述: 获取来地IP地址
# 参数: 
# 返回: ip addr
# 实例: get_local_ip
########################################
function __get_local_ip__(){
    local local_ip
    local_ip="$(ip addr show $1 2> /dev/null | awk '/inet / {print $2; exit}')"
    local_ip="${local_ip/\/*}"
    [[ "$local_ip" ]] || local_ip="$(ifconfig $1 2> /dev/null | awk '/broadcast/ {print $2; exit}')"
    echo local_ip
    unset local_ip
}

function get_local_ip() {
    local local_ip
    case $CURRENT_OPERATING_SYSTEM in
        "Linux" | "BSD" | "Solaris" | "AIX" | "IRIX")
        case $local_ip_interface in
            auto)
                local_ip="$(ip route get 1 | awk -F'src' '{print $2; exit}')"
                local_ip="${local_ip/uid*}"
                [[ "$local_ip" ]] || local_ip="$(ifconfig -a | awk '/broadcast/ {print $2; exit}')"
                ;;
            *)
                local_ip=$(__get_local_ip__ 'en0')
                [[ -z "$local_ip" ]] && local_ip=$(__get_local_ip__ "en1")
                ;;
        esac
        ;;

        "MINIX")
            local_ip="$(ifconfig | awk '{printf $3; exit}')"
        ;;

        "Mac OS X" | "macOS" | "iPhone OS")
            case $local_ip_interface in
                auto)
                    local interface="$(route get 1 | awk -F': ' '/interface/ {printf $2; exit}')"
                    local_ip="$(ipconfig getifaddr "$interface")"
                    unset interface
                    ;;
                *)
                    local_ip="$(ipconfig getifaddr en0)"
                    [[ -z "$local_ip" ]] && local_ip="$(ipconfig getifaddr en1)"
                    ;;
            esac
        ;;

        "Windows")
            local_ip="$(ipconfig | awk -F ': ' '/IPv4 Address/ {printf $2 ", "}')"
            local_ip="${local_ip%\,*}"
        ;;

        "Haiku")
            local_ip="$(ifconfig | awk -F ': ' '/Bcast/ {print $2}')"
            local_ip="${local_ip/, Bcast}"
        ;;
    esac
    printf '%s' ${local_ip}
    unset local_ip
}

########################################
# 描述: 网址转IP地址
# 参数: public_ip_host
# 返回: ip addr
# 实例: get_public_ip
########################################
function get_public_ip() {
    local public_ip
    if [[ ! -n "$public_ip_host" ]] && type -p dig >/dev/null; then
        public_ip="$(dig +time=1 +tries=1 +short myip.opendns.com @resolver1.opendns.com)"
       [[ "$public_ip" =~ ^\; ]] && unset public_ip
    fi

    if [[ ! -n "$public_ip_host" ]] && [[ -z "$public_ip" ]] && type -p drill >/dev/null; then
        public_ip="$(drill myip.opendns.com @resolver1.opendns.com | \
                     awk '/^myip\./ && $3 == "IN" {print $5}')"
    fi

    if [[ -z "$public_ip" ]] && type -p curl >/dev/null; then
        public_ip="$(curl -L --max-time "$public_ip_timeout" -w '\n' "$public_ip_host")"
    fi

    if [[ -z "$public_ip" ]] && type -p wget >/dev/null; then
        public_ip="$(wget -T "$public_ip_timeout" -qO- "$public_ip_host")"
    fi
    printf '%s' ${public_ip}
    unset public_ip
}
########################################
# 描述: 获取当前用户和主机名
# 参数: 
# 返回: user@hostname
# 实例: get_system_title
########################################
function get_system_title() {
    local user="${USER:-$(whoami || printf "%s" "${HOME/*\/}")}"
    local hostname="${HOSTNAME:-$(hostname)}"
    
    if [[ -z $1 ]];then
        local title="${GREEN}${user}${RESET}@${GREEN}${hostname}${RESET}"
    else
        local title="${user}@${hostname}"
    fi
    
    printf '%s' ${title}
    unset user
    unset hostname
    unset ise
    unset title
}
function get_title() {
    local user="${USER:-$(whoami || printf "%s" "${HOME/*\/}")}"
    local host="${HOSTNAME:-$(hostname)}"
    local title="${GREEN}${user}${RESET}@${GREEN}${host}${RESET}"
    printf '%s\n' ${title}
    unset user
    unset host
    unset title
}

function get_users() {
    local users="$(who | awk '!seen[$1]++ {printf $1 ", "}')"
    users="${users%\,*}"
    
    printf '%s' ${users}
    unset users
}

########################################
# 描述: 获取本地化设置
# 参数: 
# 返回: lang
# 实例: get_locale
########################################
function get_locale() {
    local locale="${LANG:-"zh_CN.UTF-8"}"
    locale=${sys_locale:-${locale}}
    printf '%s' ${locale}
    unset locale
}

########################################
# 描述: 获取当前shell
# 参数: 
# 返回: shell
# 实例: get_current_shell
########################################
function get_current_shell() {
    local shell=${SHELL##*/}
    local shell_version=${1:-on}
    if [[ -z ${shell} ]];then
        shell=$(ps -p $$ | grep $$ |awk '{print $NF}')
    fi
    
    [[ $shell_version == on ]] && {
    local shell_name=${shell}
    case ${shell_name} in
        bash)
            [[ $BASH_VERSION ]] ||
                BASH_VERSION=$("$SHELL" -c "printf %s \"\$BASH_VERSION\"")

            shell+=${BASH_VERSION/-*}
        ;;

        sh|ash|dash|es) ;;

        *ksh)
            shell+=$("$SHELL" -c "printf %s \"\$KSH_VERSION\"")
            shell=${shell/ * KSH}
            shell=${shell/version}
        ;;

        osh)
            if [[ $OIL_VERSION ]]; then
                shell+=$OIL_VERSION
            else
                shell+=$("$SHELL" -c "printf %s \"\$OIL_VERSION\"")
            fi
        ;;

        tcsh)
            shell+=$("$SHELL" -c "printf %s \$tcsh")
        ;;

        yash)
            shell+=$("$SHELL" --version 2>&1)
            shell=${shell/ $shell_name}
            shell=${shell/ Yet another shell}
            shell=${shell/Copyright*}
        ;;

        nu)
            shell+=$("$SHELL" -c "version | get version")
            shell=${shell/ $shell_name}
        ;;
        
        zsh)
            if [[ $ZSH_VERSION ]]; then
                shell+=$ZSH_VERSION
            else
                shell+=$("$SHELL" -c "printf %s \"\$ZSH_VERSION\"")
            fi
        ;;

        *)
            shell+=$("$SHELL" --version 2>&1)
            shell=${shell/ $shell_name}
        ;;
    esac
    unset shell_name
    }

    # Remove unwanted info.
    shell=${shell/, version}
    shell=${shell/xonsh\//xonsh }
    shell=${shell/options*}
    shell=${shell/\(*\)}
    
    printf '%s' ${shell}
    unset shell 
}
########################################
# 描述: 获取shell版本号
# 参数: shell名
# 返回: (..)版本号
# 实例: get_shell_version "zsh"
########################################
function get_shell_version(){
    local shell=${1:-sh}
    local version=$(${shell} --version | head -n 1 | grep -oP '\K\d+\.\d+\.\d+')
    echo $version
    unset shell version
}


########################################
# 描述: 获取终端大小
# 参数: 
# 返回: 
# 实例: get_window_size
########################################
function get_window_size() {
    # This functions gets the current window size in
    # pixels.
    #
    # We first try to use the escape sequence "\033[14t"
    # to get the terminal window size in pixels. If this
    # fails we then fallback to using "xdotool" or other
    # programs.

    # Tmux has a special way of reading escape sequences
    # so we have to use a slightly different sequence to
    # get the terminal size.
    if [[ "$image_backend" == "tycat" ]]; then
        printf '%b' '\e}qs\000'

    elif [[ -z $VTE_VERSION ]]; then
        case ${TMUX:-null} in
            "null") printf '%b' '\e[14t' ;;
            *)      printf '%b' '\ePtmux;\e\e[14t\e\\ ' ;;
        esac
    fi

    # The escape codes above print the desired output as
    # user input so we have to use read to store the out
    # -put as a variable.
    # The 1 second timeout is required for older bash
    #
    # False positive.
    # shellcheck disable=2141
    local bash_version=$(get_shell_version 'bash' | cut -d '.' -f 1)
    
    case $bash_version in
        4|5) IFS=';t' read -d t -t 0.05 -sr term_size ;;
        *)   IFS=';t' read -d t -t 1 -sr term_size ;;
    esac
    unset IFS

    # Split the string into height/width.
    if [[ "$image_backend" == "tycat" ]]; then
        term_width="$((term_size[2] * term_size[0]))"
        term_height="$((term_size[3] * term_size[1]))"

    else
        term_height="${term_size[1]}"
        term_width="${term_size[2]}"
    fi

    # Get terminal width/height.
    if (( ${term_width:-0} < 50 )) && [[ "$DISPLAY" && $CURRENT_OPERATING_SYSTEM != "Mac OS X" && $CURRENT_OPERATING_SYSTEM != "macOS" ]]; then
    
        if type -p xdotool &>/dev/null; then
            IFS=$ '\n' read -d "" -r win <<< "$(xdotool getactivewindow getwindowgeometry --shell %1)"
            term_width="${win[3]/WIDTH=}"
            term_height="${win[4]/HEIGHT=}"

        elif type -p xwininfo &>/dev/null; then
            # Get the focused window's ID.
            if type -p xdo &>/dev/null; then
                current_window="$(xdo id)"

            elif type -p xprop &>/dev/null; then
                current_window="$(xprop -root _NET_ACTIVE_WINDOW)"
                current_window="${current_window##* }"

            elif type -p xdpyinfo &>/dev/null; then
                current_window="$(xdpyinfo | grep -F "focus:")"
                current_window="${current_window/*window }"
                current_window="${current_window/,*}"
            fi

            # If the ID was found get the window size.
            if [[ "$current_window" ]]; then
                term_size=("$(xwininfo -id "$current_window")")
                term_width="${term_size[0]#*Width: }"
                term_width="${term_width/$'\n'*}"
                term_height="${term_size[0]/*Height: }"
                term_height="${term_height/$'\n'*}"
            fi
        fi
    fi

    term_width="${term_width:-0}"
}


















function show_system_information(){
    local kn=$(get_kernel)
    local dt=$(get_distro)
    local lc=$(get_locale)
    local tt=$(get_title)
    local cs=$(get_current_shell)
    local cpu=$(get_cpu)
    local mem=$(get_memory)
    local upt=$(get_uptime)
    local cus=$(get_cpu_usage)
    local ter=$(get_terminal)
    local lip=$(get_local_ip)
    
    
    spec_char '\n'
    printf '%s\n' "${tt}[${RED}$(trim ${lip})${RESET}]"
    hr '-' 45
    prf "OS" "${dt}"
    prf "Kernel" "${kn}"
    prf "Terminal" "${ter}"
    prf "Shell" "${cs}"
    prf "Memory" "${mem}"
    prf "Lang" "${lc}"
    prf "Uptime" "${upt}"
    prf "CPU" "${cpu}"
    prf "Cpuuse" "${cus}"
    hr '-' 45
}


__system_init__

































